
// 防抖
function debounce(fn,delay){
    let timer=null
    return (...args)=>{
        if(timer){
            clearTimeout(timer)
            timer=null
        }
        setTimeout(()=>{
            fn(args)
            clearTimeout(timer)
            timer=null
        },delay)

    }
}

//
function throttle(fn,delay){
    let timer=null
    return (...args)=>{
        if(timer){
            return
        }
        setTimeout(()=>{
            fn(...args)
            setTimeout(timer)
            timer=null
        },delay)
    }
}

function deepClone(target,hash){
    if(typeof target!=='object'||target===null){
        return target
    }

    if (hash[target]){
       return hash[target]
    }

    let copyTarget=Array.isArray(target)?[]:{}

    for (let key in target){
        copyTarget[key]=deepClone(target[key],hash)
    }

    hash[target]=copyTarget

    return copyTarget

}

function getType(target){
    return Object.prototype.toString.call(target).match(/^\[object (.*)\]$/)[1]
}


function trim(str){
    return str.replace(/^\s+|\s+$/,'')
}

function flatArray(arr,depth){

    //
    if(depth===0){
        return arr
    }

    //
    let res=[]
    for(let item of arr){
        if(Array.isArray(item)){
            res.push(...item)
        }else {
            res.push(item)
        }
    }

    return flatArray(res,depth-1)

}


function requestRetry(url,retries=3){
    return new Promise((resolve,reject)=>{
        function attempt(){
            fetch(url).then((data)=>{
                resolve(data.json())
            }).catch(err=>{
                if (retries===0){
                    reject(err)
                }else {
                    attempt(url,retries--)
                }

            })
        }

        attempt()
    })

}

class EventBus{
    constructor(){
        this.events={}
    }

    subscribe(eventName,callback){
        if(!this.events[eventName]){
            this.events[eventName]=[]
        }
        this.events[eventName].push(callback)
    }

    unsubscribe(eventName,callback){
        if(this.events[eventName]){
            this.events[eventName]=this.events[eventName].filter(cb=>cb!==callback)
        }
    }

    publish(eventName,data){
        if(this.events[eventName]){
            this.events[eventName].forEach(callback=>{
                callback(data)
            })
        }

    }
}

function randomStr(){
    return Math.random().toString(32).slice(2)
}

function bind(target,...args){
    return (...rest)=>this.call(target,...args,...rest)
}

function sum(...args){
    const fn=(...rest)=>sum(...args,...rest)
    fn.calc=()=>args.reduce((pre,cur)=>pre+cur,0)
    return fn
}

function curry(fn,...args){
    return fn.length<args.length?fn(...args):curry.bind(null,fn,...args)

}

function shuffle(list){
    return list.sort((a,b)=>Math.random()-0.5)
}

function download(data,type,name){
    const blob= new Blob([data],{type})

    const ele=  document.createElement('a')
    ele.href=URL.createObjectURL(blob)
    ele.download=name
    ele.style.display='none'

    document.body.appendChild(ele)
    ele.click()

    URL.revokeObjectURL(ele.href)

    document.body.removeChild(ele)

}

class LRU{
    constructor(limit){
        this.limit=limit
        this.cache=new Map()
    }

    get(key){
        if(!this.cache.has(key)){
            return undefined
        }
        const value=this.cache.get(key)
        this.cache.delete(key)
        this.cache.set(key,value)

        return value
    }

    set(key,value){
        if(this.cache.has(key)){
           this.cache.delete(key)
        }
        if(this.cache.size>this.limit){
            this.cache.delete(this.cache.keys().next().value)
        }

        this.cache.set(key,value)
    }

}

function pipe(asyncFuncList){
    asyncFuncList.reduce((pre,cur)=>{

       return pre.then(cur)

    },Promise.resolve())
}

function watchTarget(target){
    const handler={
        get(target,key,receiver){
            console.log(`属性：${key}`)
            const value=Reflect.get(target,key,receiver)
            if(value instanceof Object){
                return new Proxy(value,handler)
            }
            return value
        },
    }
    return new Proxy(target,handler)
}
const handlerProxy=new watchTarget({
    first:{
        gender:'man',
        score:{
            math:100
        }
    }
})

function mySetInterval(callback,delay){
    let timer=null

    function tick(){
        callback()
        timer= setTimeout(tick,delay)
    }

    timer= setTimeout(tick,delay)

    return {
        cancel:()=>{
            clearTimeout(timer)
            timer=null
        }
    }
}


class taskManager1{
    constructor(){
        this.list=[]
        this.historyRecord={}
    }

    addTask(taskFunc){
        this.list.push(taskFunc)
    }

    analysisDependencies(taskFunc){}
    execute(){
        this.dfsAnalysis(this.list)
    }

    dfsAnalysis(taskFuncList){

        for (let taskFunc of taskFuncList){
            // 解析依赖
            const dependenciesList=this.analysisDependencies(taskFunc)

            // 检查依赖是否循环引用
            if(this.checkCycle(dependenciesList)){
                throw new Error('存在循环引用')
            }

            // 递归下一层解析依赖
            this.dfsAnalysis(dependenciesList)
            // 执行本层
            if (this.historyRecord[taskFunc]){ // 运行过，直接结束
                return
            }
            taskFunc()

            this.historyRecord[taskFunc]=true

        }


    }

    // 检测依赖列表中是否存在环形依赖
    checkCycle(dependencies){
        for (let dep of dependencies){
            if(this.historyRecord[dep]){
                return true
            }
        }
        return false

    }

}


// { id , parentId }
function buildTree(list){

}


